package com.atguigu.juc.volatiles;

import java.util.concurrent.TimeUnit;

/**
 * @author yanglin
 * @create 2024-01-23 12:50 星期二
 * description:
 */
public class VolatileSeeDemo {

    /**
     * volatile保证可见性：
     * 	说明：保证不同线程对某个变量完成操作后结果及时可见，即该共享变量一旦改变所有线程立即可见
     *  被volatile修饰的变量有两个特点：
     *      1、线程中读取的时候，每次读取都会去主内存中读取共享变量的最新值，然后将其复制到工作内存
     *      2、线程中修改了工作内存中变量的副本，修改之后会立即刷新到主内存
     *   Java内存模型中定义的8种每个线程自己的工作内存与主物理内存之间的原子操作
     *      read(读取)->load(加载)->use(使用)->assign(赋值)->store(存储)->write(写入)->lock(锁定)->unlock(解锁)
     *      read：作用于主内存，将变量的值从主内存传输到工作内存，主内存到工作内存
     *      load：作用于工作内存，将read从主内存传输到的变量值放入工作内存变量副本中，即数据加载
     *      use：作用于工作内存，将工作内存变量副本的值传递给执行引擎，每当JVM遇到需要该变量的字节码指令时会执行该操作
     *      assign：作用于工作内存，将从执行引擎接收到的值赋值给工作内存变量，每当JVM遇到一个给变量赋值字节码指令时会执行该操作
     *      store：作用于工作内存，将赋值完毕的工作变量的值写回给主内存
     *      write：作用于主内存，将store传输过来的变量赋值给主内存中的变量
     *      上述6条，只能保证单条指令的原子性
     *      lock：作用于主内存，将一个变量标记为一个线程独占的状态，只是写时候加锁，就只是锁了写变量的过程
     *      unlock：作用域主内存，把一个处于锁定状态的变量释放，然后才能被其他线程占用
     */
    
    
    //保证线程之间可见（volatile保证可见性）
    volatile static boolean flag = true;
    
    public static void main(String[] args) {
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "\t come in");
            while (flag){
                
            }
            System.out.println(Thread.currentThread().getName() + "\t flag 被设置为false，程序停止");
        },"t1").start();

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        flag = false;
        System.out.println(Thread.currentThread().getName() + "\t 修改完成");
    }
    
    
    
}
